package com.zoe.onelink.business.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.zoe.onelink.util.ValidUtil;
import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.*;
import java.util.*;

/**
 * XMl工具类
 *
 * @author lsy
 */
@Deprecated
public class XmlUtil {

    /**
     * 获取Document对象
     *
     * @param filePath xml文件路径
     * @return
     * @throws Exception
     */
    public static Document getDocument(String filePath) throws Exception {
        File file = null;
        try {
            file = new File(filePath);
        } catch (Exception e) {
            throw new Exception("读取Xml文件出错！路径为:" + filePath + "。");
        }
        return XmlUtil.getDocument(file);
    }

    /**
     * 获取Document对象
     *
     * @param file xml文件
     * @return
     * @throws Exception
     */
    public static Document getDocument(File file) throws Exception {
        SAXReader xmlReader = new SAXReader();
        return xmlReader.read(file);
    }

    /**
     * 获取Document对象
     *
     * @param is 输入流
     * @return
     * @throws Exception
     */
    public static Document getDocument(InputStream is) throws Exception {
        SAXReader xmlReader = new SAXReader();
        return xmlReader.read(is);
    }

    /**
     * 获取Document对象
     *
     * @param str xml字符串
     * @return
     * @throws Exception
     */
    public static Document getDocumentFromStr(String str) throws Exception {
        if (ValidUtil.isEmptyOrNull(str)) {
            return null;
        }
        SAXReader xmlReader = new SAXReader();
        return xmlReader.read(new ByteArrayInputStream(str.getBytes("utf-8")));
    }

    /**
     * 获取Document对象
     *
     * @param str      xml字符串
     * @param encoding 编码
     * @return
     * @throws Exception
     */
    public static Document getDocumentFromStr(String str, String encoding) throws Exception {
        if (ValidUtil.isEmptyOrNull(str)) {
            return null;
        }
        SAXReader xmlReader = new SAXReader();
        int a = str.indexOf("encoding=\"");
        int b = str.indexOf("\"?>");
        try {
            String xmlEncode = str.substring(a + 10, b);
            encoding = xmlEncode;
        } catch (Exception e) {
            throw new Exception("获取Document对象", e);
        }

        return xmlReader.read(new ByteArrayInputStream(str.getBytes(encoding)));
    }

    /**
     * 获取Document对象
     *
     * @param str xml字符串
     * @return
     * @throws Exception
     */
    public static Document autoDoctumentStr(String str) throws Exception {
        try {
            String encode = "";
            if (!ValidUtil.isEmptyOrNull(str)) {
                str = str.trim();//去掉xml首尾空格
            }
            Document doc = DocumentHelper.parseText(str);
            encode = doc.getXMLEncoding();
            return getDocumentFromStr(str, encode);
        } catch (Exception e) {
            try {
                return getDocumentFromStr(str, "UTF-8");
            } catch (Exception e1) {
                try {
                    return getDocumentFromStr(str, "GB2312");
                } catch (Exception e2) {
                    throw new Exception("解析xml错误，未知的xml编码或错误的xml格式。");
                }
            }
        }
    }

    /**
     * 对象转成xml字符串
     *
     * @param t 对象
     * @return
     * @throws Exception
     */
    public static <T> String toXml(T t) throws Exception {
        try {
            XStream xs = new XStream();
            xs.processAnnotations(t.getClass());
            return xs.toXML(t).replaceAll("&quot;", "\"");
        } catch (Exception e) {
            throw new Exception("对象转换成Xml文本出错！", e);
        }
    }

    /**
     * 根据xml字符串生成对象
     *
     * @param xmlStr
     * @param cls
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static <T> T toBean(String xmlStr, Class<T> cls) throws Exception {
        try {
            XStream xs = new XStream(new DomDriver());
            xs.processAnnotations(cls);
            return (T) xs.fromXML(xmlStr);
        } catch (Exception e) {
            throw new Exception("Xml文本转换成对象出错！", e);
        }
    }

    /**
     * 根据xmlStr生成model,须要在model类加上@XmlRootElement(name="根节点名字")
     *
     * @param xmlStr
     * @return model类的实例
     * @author cgf
     * @createTime 2015-01-10
     */
    @SuppressWarnings("unchecked")
    public static <T> T toModel(String xmlStr, Class<T> cls) throws Exception {
        try {
            JAXBContext context = JAXBContext.newInstance(cls);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            return (T) unmarshaller.unmarshal(new StringReader(xmlStr));
        } catch (Exception e) {
            throw new Exception("Xml文本转换成对象出错！" + e.getMessage(), e);
        }
    }

    /**
     * map转成xml
     *
     * @param map      集合
     * @param nodeName 集合节点名称
     */
    public static String map2Xml(Map map, String nodeName) throws Exception {
        StringBuffer sb = new StringBuffer();
        mapToXml(map, sb, nodeName);
        return sb.toString();
    }

    /**
     * map转成xml
     */

    public static String map2Xml(Map map) throws Exception {
        StringBuffer sb = new StringBuffer();
        try {
            Set set = map.keySet();
            Iterator it = set.iterator();

            while (true) {
                while (it.hasNext()) {
                    String key = (String) it.next();
                    Object value = map.get(key);
                    if (null == value) {
                        value = "";
                    }

                    if (value instanceof List) {
                        List list = (List) map.get(key);

                        for (int i = 0; i < list.size(); ++i) {
                            sb.append("<" + key + ">");
                            Map hm = (Map) list.get(i);
                            mapToXml2(hm, sb);
                            sb.append("</" + key + ">");
                        }

                    } else if (value instanceof Map) {
                        sb.append("<" + key + ">");
                        mapToXml2((Map) value, sb);
                        sb.append("</" + key + ">");
                    } else {
                        sb.append("<" + key + ">" + value + "</" + key + ">");
                    }
                }

                return sb.toString();
            }
        } catch (Exception var10) {
            throw new Exception("对象转换成Xml文本出错！", var10);
        }
    }

    /**
     * map转成xml
     * 原样输出，不转下划线
     *
     * @param map      集合
     * @param nodeName 集合节点名称
     */
    public static String map2XmlBySample(Map map, String nodeName) throws Exception {
        StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"utf-8\"?><root>");
        mapToXml(map, sb, nodeName);
        return sb.append("</root>").toString();
    }

    /**
     * map转成xml实际操作
     *
     * @param map      集合
     * @param sb       字符串
     * @param nodeName 集合节点名称
     */
    public static void mapToXml(Map map, StringBuffer sb, String nodeName) throws Exception {
        try {
            Set set = map.keySet();
            for (Iterator it = set.iterator(); it.hasNext(); ) {
                String key = (String) it.next();
                Object value = map.get(key);
                if (null == value) {
                    value = "";
                }
                if (value.getClass().getName().equals("java.util.ArrayList")) {
                    ArrayList list = (ArrayList) map.get(key);
                    sb.append("<" + key + ">");
                    for (int i = 0; i < list.size(); i++) {
                        if (!ValidUtil.isEmptyOrNull(nodeName)) {
                            sb.append("<" + nodeName + ">");
                        }
                        HashMap hm = (HashMap) list.get(i);
                        mapToXml(hm, sb, key);
                        if (!ValidUtil.isEmptyOrNull(nodeName)) {
                            sb.append("</" + nodeName + ">");
                        }
                    }
                    sb.append("</" + key + ">");
                } else {
                    if (value instanceof HashMap) {
                        sb.append("<" + key + ">");
                        mapToXml((HashMap) value, sb, nodeName);
                        sb.append("</" + key + ">");
                    } else {
                        sb.append("<" + key + ">" + value + "</" + key + ">");
                    }
                }
            }
        } catch (Exception e) {
            throw new Exception("对象转换成Xml文本出错！", e);
        }
    }

    /**
     * xml转map 不带属性
     *
     * @param xmlStr
     * @param needRootKey 是否需要在返回的map里加根节点键
     * @return
     * @throws DocumentException
     */
    public static Map xml2map(String xmlStr, boolean needRootKey) throws DocumentException {
        Document doc = DocumentHelper.parseText(xmlStr);
        Element root = doc.getRootElement();
        Map<String, Object> map = (Map<String, Object>) xml2map(root);
        if (root.elements().size() == 0 && root.attributes().size() == 0) {
            return map;
        }
        if (needRootKey) {
            //在返回的map里加根节点键（如果需要）
            Map<String, Object> rootMap = new HashMap<String, Object>();
            rootMap.put(root.getName(), map);
            return rootMap;
        }
        return map;
    }

    /**
     * xml转map 带属性
     *
     * @param xmlStr
     * @param needRootKey 是否需要在返回的map里加根节点键
     * @return
     * @throws DocumentException
     */
    public static Map xml2mapWithAttr(String xmlStr, boolean needRootKey) throws DocumentException {
        Document doc = DocumentHelper.parseText(xmlStr);
        Element root = doc.getRootElement();
        Map<String, Object> map = (Map<String, Object>) xml2mapWithAttr(root);
        if (root.elements().size() == 0 && root.attributes().size() == 0) {
            return map; //根节点只有一个文本内容
        }
        if (needRootKey) {
            //在返回的map里加根节点键（如果需要）
            Map<String, Object> rootMap = new HashMap<String, Object>();
            rootMap.put(root.getName(), map);
            return rootMap;
        }
        return map;
    }

    /**
     * xml转map 不带属性
     *
     * @param e
     * @return
     */
    private static Map xml2map(Element e) throws DocumentException {
        Map map = new LinkedHashMap();
        List list = e.elements();
        if (list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                Element iter = (Element) list.get(i);
                List mapList = new ArrayList();

                if (iter.elements().size() > 0) {
                    Map m = xml2map(iter);
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!(obj instanceof List)) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(m);
                        }
                        if (obj instanceof List) {
                            mapList = (List) obj;
                            mapList.add(m);
                        }
                        map.put(iter.getName(), mapList);
                    } else {
                        map.put(iter.getName(), m);
                    }
                } else {
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!(obj instanceof List)) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(iter.getText());
                        }
                        if (obj instanceof List) {
                            mapList = (List) obj;
                            mapList.add(iter.getText());
                        }
                        map.put(iter.getName(), mapList);
                    } else {
                        map.put(iter.getName(), iter.getText());
                    }
                }
            }
        } else {
            map.put(e.getName(), e.getText());
        }
        return map;
    }

    /**
     * xml转map 带属性
     *
     * @param element
     * @return
     */
    private static Map xml2mapWithAttr(Element element) throws DocumentException {
        Map<String, Object> map = new LinkedHashMap<String, Object>();

        List<Element> list = element.elements();
        List<Attribute> listAttr0 = element.attributes(); // 当前节点的所有属性的list
        for (Attribute attr : listAttr0) {
            map.put("@" + attr.getName(), attr.getValue());
        }
        if (list.size() > 0) {

            for (int i = 0; i < list.size(); i++) {
                Element iter = list.get(i);
                List mapList = new ArrayList();

                if (iter.elements().size() > 0) {
                    Map m = xml2mapWithAttr(iter);
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!(obj instanceof List)) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(m);
                        }
                        if (obj instanceof List) {
                            mapList = (List) obj;
                            mapList.add(m);
                        }
                        map.put(iter.getName(), mapList);
                    } else {
                        map.put(iter.getName(), m);
                    }
                } else {

                    List<Attribute> listAttr = iter.attributes(); // 当前节点的所有属性的list
                    Map<String, Object> attrMap = null;
                    boolean hasAttributes = false;
                    if (listAttr.size() > 0) {
                        hasAttributes = true;
                        attrMap = new LinkedHashMap<String, Object>();
                        for (Attribute attr : listAttr) {
                            attrMap.put("@" + attr.getName(), attr.getValue());
                        }
                    }

                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!(obj instanceof List)) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            // mapList.add(iter.getText());
                            if (hasAttributes) {
                                attrMap.put("#text", iter.getText());
                                mapList.add(attrMap);
                            } else {
                                mapList.add(iter.getText());
                            }
                        }
                        if (obj instanceof List) {
                            mapList = (List) obj;
                            // mapList.add(iter.getText());
                            if (hasAttributes) {
                                attrMap.put("#text", iter.getText());
                                mapList.add(attrMap);
                            } else {
                                mapList.add(iter.getText());
                            }
                        }
                        map.put(iter.getName(), mapList);
                    } else {
                        // map.put(iter.getName(), iter.getText());
                        if (hasAttributes) {
                            attrMap.put("#text", iter.getText());
                            map.put(iter.getName(), attrMap);
                        } else {
                            map.put(iter.getName(), iter.getText());
                        }
                    }
                }
            }
        } else {
            // 根节点的
            if (listAttr0.size() > 0) {
                map.put("#text", element.getText());
            } else {
                map.put(element.getName(), element.getText());
            }
        }
        return map;
    }

    /**
     * 对象List集合转成xml字符串
     *
     * @param list     对象集合
     * @param nodeName 节点名称
     * @return
     * @throws Exception
     */
    public static <T> String ListBean2Xml(List<T> list, String nodeName) throws Exception {
        StringBuffer xml = new StringBuffer();
        try {
            for (T t : list) {
                XStream xs = new XStream();
                xs.alias(nodeName, t.getClass());
                xs.processAnnotations(t.getClass());
                xml.append(xs.toXML(t));
            }
            return xml.toString().replaceAll("&quot;", "\"");
        } catch (Exception e) {
            throw new Exception("对象转换成Xml文本出错！", e);
        }
    }

    public static String DocumentToString(Document doc, String encoding) throws IOException {
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding(encoding);
        StringWriter out = new StringWriter(1024);
        XMLWriter xmlWriter = new XMLWriter(out, format);
        xmlWriter.write(doc);
        return out.toString();
    }

    public static JSONObject xmlStrToJSONObject(String xml, boolean needRoot) throws DocumentException {
        return new JSONObject(xml2map(xml, needRoot));
    }

    public static <T> T xmlStrToObject(String text, boolean needRoot, Class<T> clazz) throws DocumentException {
        return JSON.parseObject(xmlStrToJSONObject(text, needRoot).toJSONString(), clazz);
    }

    public static Map jsonToMap(String jsonStr) {
        return JSON.parseObject(jsonStr, Map.class);
    }
//    public static String objectToXml(Object o){
//        jsonToMap(JSON.toJSON(o).toString());
//    }

    public static String objToXml2(Object o) throws Exception {
        return map2Xml2(JSON.parseObject((JSON.toJSONString(o, SerializerFeature.WriteMapNullValue))));
    }

    /**
     * 多层（Map  List ; 将
     */
    public static String map2Xml2(Map map) throws Exception {
        StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"utf-8\"?><root>");
        mapToXml2(map, sb);
        return sb.append("</root>").toString();
    }

    /**
     * 多层（Map  List ; 将
     */

    public static void mapToXml2(Map map, StringBuffer sb) throws Exception {
        try {
            Set set = map.keySet();
            Iterator it = set.iterator();

            while (true) {
                while (it.hasNext()) {
                    String key = (String) it.next();
                    Object value = map.get(key);
                    if (null == value) {
                        value = "";
                    }

                    if (value instanceof List) {
                        List list = (List) map.get(key);

                        for (int i = 0; i < list.size(); ++i) {
                            sb.append("<" + key + ">");
                            Map hm = (Map) list.get(i);
                            mapToXml2(hm, sb);
                            sb.append("</" + key + ">");
                        }

                    } else if (value instanceof Map) {
                        sb.append("<" + key + ">");
                        mapToXml2((Map) value, sb);
                        sb.append("</" + key + ">");
                    } else {

                        sb.append("<" + key + ">" + value + "</" + key + ">");
                    }
                }

                return;
            }
        } catch (Exception var10) {
            throw new Exception("对象转换成Xml文本出错！", var10);
        }
    }

}

